package com.yjzx.util.binlog.core.util;


import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author yjzx
 * @date 2024/6/13
 * @description CollectorUtil
 */
public class CollectionUtil {
    public static <T> Predicate<T> toTrue() {
        return t -> true;
    }

    /**
     * 因stream流 value无法存在null，重写tomap
     *
     * @param collections
     * @param keyMapper
     * @param valueMapper
     * @param <T>
     * @param <K>
     * @param <V>
     * @return
     */
    public static <T, K, V> Map<K, V> toMap(Collection<T> collections, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
        return toMap(collections, toTrue(), keyMapper, valueMapper);
    }

    public static <T, K, V> Map<K, V> toMap(Collection<T> collections, Predicate<? super T> predicate, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
        int size = collections.size();
        size = hashMapSize(size);
        Map<K, V> map = new HashMap<>(size);
        for (T collection : collections) {
            if (predicate.test(collection)) {
                map.put(keyMapper.apply(collection), valueMapper.apply(collection));
            }
        }
        return map;
    }
    public static <T, K, V> Map<K, List<V>> toMapValueList(Collection<T> collections, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
        return toMapValueList(collections, toTrue(), keyMapper, valueMapper);
    }
    public static <T, K, V> Map<K, List<V>> toMapValueList(Collection<T> collections,Predicate<? super T> predicate, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
        Map<K, List<V>> map = new HashMap<>(16);
        for (T collection : collections) {
            if (predicate.test(collection)) {
                K k = keyMapper.apply(collection);
                V v = valueMapper.apply(collection);
                map.putIfAbsent(k, new ArrayList<>());
                map.get(k).add(v);
            }
        }
        return map;
    }
    private static int hashMapSize(int size) {
        size = (int) (size / 0.75);
        int a = 1;
        while (size > 1) {
            size = size >> 1;
            a++;
        }
        size = 1 << Math.min(a, 8);
        return size;
    }
}
